<!DOCTYPE html>
<html lang="en">
    <head>
    <title>Rust - Limitations - 1 - Tinusgraglin</title>
    
    
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1"><meta name="description" content="A Slice Rust - Limitations - 1 Of course, it&#x27;s not yet done, and its&#x27;s hard to design perfect things."/><meta name="keywords" content="rust, rust-language, rust-limitations" />
    <meta property="og:title" content="A Slice of Tgl -&nbsp;Rust - Limitations - 1" />
    <meta property="og:type" content="website"/><meta property="og:url" content="&#x2F;blog&#x2F;rust-limitations-1&#x2F;"/><meta property="og:description" content="Of course, it&#x27;s not yet done, and its&#x27;s hard to design perfect things."/>
    <link rel="preload" href="/blog/assets/fonts/FiraCode-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
    <link rel="preload" href="/blog/assets/fonts/FiraCode-Bold.woff2" as="font" type="font/woff2" crossorigin="anonymous">

    <link rel="stylesheet" href="/blog/style.css?h=97e262212a0704163528">
    <link rel="stylesheet" href=" /blog/color/orange.css?h=a5a5d7faf9d4bc3e0b18">
    
</head>
    <body>
        <div class="container center">
<header class="header">
    <div class="header__inner">
        <div class="header__logo">
            <a href="&#x2F;blog">
    <div class="logo">
        LIN
    </div>
</a>
        </div>
        <div class="menu-trigger">menu</div>
    </div>
    
    <nav class="menu">
        <ul class="menu__inner menu__inner--desktop">
            
            
                    <li>
                        <a href="
    
        /blog/about
    
">about</a>
                    </li>
                
            </ul>

        <ul class="menu__inner menu__inner--mobile">
            
        <li>
            <a href="
    
        /blog/about
    
">about</a>
        </li>
        </ul>
    </nav>

    </header>
<div class="content"><article class="post">
        <header>
            <h1 class="post-title">
                <a href="&#x2F;blog&#x2F;rust-limitations-1&#x2F;">Rust - Limitations - 1</a>
            </h1>
            
    <div class="post-meta">
        <span class="post-date">2023.12.29
                [Updated: 2024.01.29]
                </span>

        <span class="post-author"></span>

        

    
    :: {<a href="/blog/categories/rust/">rust</a>} 

            
    ::
    #<a href="/blog/tags/rust-language/">rust-language</a>
        
    #<a href="/blog/tags/rust-limitations/">rust-limitations</a>
        
    
            
        
    </div>

            
    


<div class="toc" id="nav-container">
	<p class="toc-head">Table of Contents</p>
		<div id="nav-content" >
		<ul>
		
			<li>
				<a href="/blog/rust-limitations-1/#reborrowings-are-not-after-all-possible-type-inferences">Reborrowings Are NOT After All Possible Type Inferences</a>
				
			</li>
		
			<li>
				<a href="/blog/rust-limitations-1/#lifetimes-of-closures">Lifetimes of Closures</a>
				
					<ul>
						
							<li>
								<a href="/blog/rust-limitations-1/#argument-lifetime-problems">Argument Lifetime Problems</a>
							</li>
							
								<ul>
								
									<li>
										<a href="/blog/rust-limitations-1/#for-all-vs-for-specific">For All vs For Specific</a>
										
									</li>
								
								</ul>
							
						
							<li>
								<a href="/blog/rust-limitations-1/#return-type-limitation">Return Type Limitation</a>
							</li>
							
						
							<li>
								<a href="/blog/rust-limitations-1/#workarounds">Workarounds</a>
							</li>
							
						
					</ul>
				
			</li>
		
			<li>
				<a href="/blog/rust-limitations-1/#references">References</a>
				
			</li>
		
		</ul>
		</div>
</div>

</header><h1 id="reborrowings-are-not-after-all-possible-type-inferences">Reborrowings Are NOT After All Possible Type Inferences<a class="zola-anchor" href="#reborrowings-are-not-after-all-possible-type-inferences" aria-label="Anchor link for: reborrowings-are-not-after-all-possible-type-inferences">§</a>
</h1>
<p>'Reborrowing' of a reference, as a type of coercion, needs the information of
the 'source' and 'destination' type. But it's not the case that a reborrowing
only happens after all type inferences are done, so in some cases, when the type
information isn't complete, reborrowing does not happen as one would expect:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">let mut</span><span> n: </span><span style="color:#b48ead;">i32 </span><span>= </span><span style="color:#d08770;">42</span><span>;
</span><span style="color:#b48ead;">let</span><span> r1 = &amp;</span><span style="color:#b48ead;">mut</span><span> n;
</span><span>
</span><span style="color:#65737e;">// Works, it&#39;s known that `r2` is a mutable reference, a reborrow take
</span><span style="color:#65737e;">// places here:
</span><span style="color:#b48ead;">let</span><span> r2: &amp;</span><span style="color:#b48ead;">mut </span><span>_ = r1;
</span><span style="color:#65737e;">// Error, `r1` is moved here because reborrow isn&#39;t triggered when the
</span><span style="color:#65737e;">// type of `r2` is not known:
</span><span style="color:#b48ead;">let</span><span> r2 = r1;
</span><span style="color:#65737e;">// Also works, here it is also known that `r2` is a mutable reference:
</span><span style="color:#b48ead;">let</span><span> r2 = &amp;</span><span style="color:#b48ead;">mut </span><span>*r1;
</span><span>
</span><span>*r1 = </span><span style="color:#d08770;">43</span><span>;
</span></code></pre>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">func</span><span>&lt;T&gt;(</span><span style="color:#bf616a;">a</span><span>: T, </span><span style="color:#bf616a;">b</span><span>: T) {}
</span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">test</span><span>&lt;T&gt;(</span><span style="color:#bf616a;">a</span><span>: &amp;</span><span style="color:#b48ead;">mut</span><span> T, </span><span style="color:#bf616a;">b</span><span>: &amp;</span><span style="color:#b48ead;">mut</span><span> T) {
</span><span>    </span><span style="color:#96b5b4;">func</span><span>(a, b);
</span><span>    </span><span style="color:#65737e;">// Error: `a` is moved. But we are free to use `b`:
</span><span>    </span><span style="color:#96b5b4;">func</span><span>(a, b);
</span><span>}
</span></code></pre>
<h1 id="lifetimes-of-closures">Lifetimes of Closures<a class="zola-anchor" href="#lifetimes-of-closures" aria-label="Anchor link for: lifetimes-of-closures">§</a>
</h1>
<p>Closures are nothing but a auto-generated <code>struct</code> that auto-implements special traits
(<code>FnOnce</code>, <code>FnMut</code>, <code>Fn</code>) that have a special <code>call</code> method, you can think of these
traits defined as:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">trait </span><span>FnOnce&lt;Arg&gt; {
</span><span>    </span><span style="color:#b48ead;">type </span><span>Output;
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>(</span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: Arg) -&gt; </span><span style="color:#b48ead;">Self::</span><span>Output;
</span><span>}
</span><span>
</span><span style="color:#b48ead;">trait </span><span>FnMut&lt;Arg&gt;: FnOnce&lt;Arg&gt; {
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>(&amp;</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: Arg) -&gt; &lt;</span><span style="color:#b48ead;">Self </span><span>as FnOnce&gt;::Output;
</span><span>}
</span><span>
</span><span style="color:#b48ead;">trait </span><span>Fn&lt;Arg&gt;: FnMut&lt;Arg&gt; {
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>(&amp;</span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: Arg) -&gt; &lt;</span><span style="color:#b48ead;">Self </span><span>as FnOnce&gt;::Output;
</span><span>}
</span></code></pre>
<p>These definations are accurate enough for our discussion into the limitations
of Rust's closures.</p>
<h2 id="argument-lifetime-problems">Argument Lifetime Problems<a class="zola-anchor" href="#argument-lifetime-problems" aria-label="Anchor link for: argument-lifetime-problems">§</a>
</h2>
<h3 id="for-all-vs-for-specific">For All vs For Specific<a class="zola-anchor" href="#for-all-vs-for-specific" aria-label="Anchor link for: for-all-vs-for-specific">§</a>
</h3>
<p>As the following example shows, a closure can work for a wide range of
arguments or a specific type of arguments:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">struct </span><span>Captured;
</span><span>
</span><span style="color:#65737e;">// `Captured` implements `FnMut&lt;&amp;&#39;a str&gt;` for all `&#39;a`, i.e.
</span><span style="color:#65737e;">// the `call` signature is like `Captured.call&lt;&#39;a&gt;(&amp;&#39;a mut str)`, it
</span><span style="color:#65737e;">// can be used for any `&amp;mut str`
</span><span style="color:#b48ead;">impl</span><span>&lt;</span><span style="color:#b48ead;">&#39;arg</span><span>&gt; FnMut&lt;&amp;</span><span style="color:#b48ead;">&#39;arg mut str</span><span>&gt; </span><span style="color:#b48ead;">for </span><span>Captured {
</span><span>    </span><span style="color:#b48ead;">type </span><span>Output = ();
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>(&amp;</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: &amp;</span><span style="color:#b48ead;">&#39;arg mut str</span><span>) -&gt; </span><span style="color:#b48ead;">Self::</span><span>Output { }
</span><span>}
</span><span>
</span><span style="color:#65737e;">// Let&#39;s call the lifetime of a `Captured` `&#39;captured`, then
</span><span style="color:#65737e;">// here `Captured` only implements `FnMut&lt;&amp;&#39;captured mut str&gt;` for
</span><span style="color:#65737e;">// a specific `&#39;captured`:
</span><span style="color:#b48ead;">impl </span><span>FnMut&lt;&amp;</span><span style="color:#b48ead;">&#39;captured mut str</span><span>&gt; </span><span style="color:#b48ead;">for </span><span>Captured {
</span><span>    </span><span style="color:#b48ead;">type </span><span>Output = ();
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>(&amp;</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: &amp;</span><span style="color:#b48ead;">&#39;captured mut str</span><span>) -&gt; </span><span style="color:#b48ead;">Self::</span><span>Output { }
</span><span>}
</span></code></pre>
<p>Unfortunately, the compiler can not determine which one is needed for each
and every case, and use a rather basic rule to decide:
If the argument is type annotated, it is the first case, otherwise, it is the
second case:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#65737e;">// `r` infered to have a specific lifetime:
</span><span style="color:#b48ead;">let </span><span style="color:#8fa1b3;">f1 </span><span>= |</span><span style="color:#bf616a;">r</span><span>| {};
</span><span style="color:#65737e;">// `r` infered to have a higher kinded (any) lifetime:
</span><span style="color:#b48ead;">let </span><span style="color:#8fa1b3;">f2 </span><span>= |</span><span style="color:#bf616a;">_r</span><span>: &amp;</span><span style="color:#b48ead;">mut i32</span><span>| {};
</span><span style="color:#65737e;">// What if you just want the type annotatation, but not the
</span><span style="color:#65737e;">// higher kinded lifetime?
</span><span style="color:#65737e;">// One workaround is like this:
</span><span style="color:#b48ead;">let </span><span style="color:#8fa1b3;">f3 </span><span>= |</span><span style="color:#bf616a;">r</span><span>| { </span><span style="color:#b48ead;">let</span><span> r: &amp;</span><span style="color:#b48ead;">mut i32 </span><span>= r; }
</span><span>
</span><span style="color:#b48ead;">let mut</span><span> n = </span><span style="color:#d08770;">42</span><span>;
</span><span>
</span><span style="color:#65737e;">// Doesn&#39;t work, the first borrow lives as long as the `f1` lives:
</span><span style="color:#96b5b4;">f1</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span><span style="color:#96b5b4;">f1</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span><span>
</span><span style="color:#65737e;">// Works:
</span><span style="color:#96b5b4;">f2</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span><span style="color:#96b5b4;">f2</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span></code></pre>
<h2 id="return-type-limitation">Return Type Limitation<a class="zola-anchor" href="#return-type-limitation" aria-label="Anchor link for: return-type-limitation">§</a>
</h2>
<p>Without special handling, the return type of a closure might only use lifetimes concerning
the closure type itself:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#65737e;">// One might think this is equivalent to `fn f1&lt;&#39;a&gt;(&amp;&#39;a mut i32) -&gt; &amp;&#39;a mut i32`,
</span><span style="color:#65737e;">// but it&#39;s actually `fn f1&lt;&#39;a&gt;(&amp;&#39;a mut i32) -&gt; &amp;&#39;captured i32`, so the compiler
</span><span style="color:#65737e;">// complains that `&#39;a` should outlive `&#39;captured`:
</span><span style="color:#b48ead;">let </span><span style="color:#8fa1b3;">f1 </span><span>= |</span><span style="color:#bf616a;">x</span><span>: &amp;</span><span style="color:#b48ead;">mut i32</span><span>| x;
</span><span>
</span><span style="color:#b48ead;">struct </span><span>Captured;
</span><span style="color:#b48ead;">impl</span><span>&lt;</span><span style="color:#b48ead;">&#39;arg</span><span>&gt; FnMut&lt;&amp;</span><span style="color:#b48ead;">&#39;arg str</span><span>&gt; </span><span style="color:#b48ead;">for </span><span>Captured {
</span><span>    </span><span style="color:#65737e;">// The compiler uses `&#39;captured` even though `&#39;arg` is usable.
</span><span>    </span><span style="color:#b48ead;">type </span><span>Output = &amp;</span><span style="color:#b48ead;">&#39;captured str</span><span>;
</span><span>
</span><span>    </span><span style="color:#65737e;">// And, notably, it&#39;s also impossible to use `&#39;lself` defined here.
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">call</span><span>&lt;</span><span style="color:#b48ead;">&#39;lself</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;lself mut </span><span style="color:#bf616a;">self</span><span>, </span><span style="color:#bf616a;">arg</span><span>: &amp;</span><span style="color:#b48ead;">&#39;arg str</span><span>) -&gt; </span><span style="color:#b48ead;">Self::</span><span>Output {
</span><span>        arg
</span><span>    }
</span><span>}
</span></code></pre>
<h2 id="workarounds">Workarounds<a class="zola-anchor" href="#workarounds" aria-label="Anchor link for: workarounds">§</a>
</h2>
<ul>
<li>Use the type system to give hints to the compiler:<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">enforce</span><span>&lt;F: for&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; Fn(&amp;</span><span style="color:#b48ead;">&#39;a mut i32</span><span>) -&gt; &amp;</span><span style="color:#b48ead;">&#39;a mut i32</span><span>&gt;(</span><span style="color:#bf616a;">f</span><span>: F) -&gt; F { f }
</span><span style="color:#b48ead;">let mut</span><span> n = </span><span style="color:#d08770;">42</span><span>;
</span><span style="color:#b48ead;">let</span><span> f = </span><span style="color:#96b5b4;">enforce</span><span>(|</span><span style="color:#bf616a;">x</span><span>| { x });
</span><span style="color:#96b5b4;">f</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span><span style="color:#96b5b4;">f</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span></code></pre>
</li>
<li>Use the <a href="https://rust-lang.github.io/rfcs/3216-closure-lifetime-binder.html">closure lifetime binder (not stable yet)</a>:<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">let mut</span><span> n = </span><span style="color:#d08770;">42</span><span>;
</span><span style="color:#b48ead;">let</span><span> f = </span><span style="color:#b48ead;">for</span><span>&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; |x: &amp;</span><span style="color:#b48ead;">&#39;a mut i32</span><span>| -&gt; &amp;</span><span style="color:#b48ead;">&#39;a mut i32 </span><span>{ x };
</span><span style="color:#96b5b4;">f</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span><span style="color:#96b5b4;">f</span><span>(&amp;</span><span style="color:#b48ead;">mut</span><span> n);
</span></code></pre>
</li>
<li>Use functions, if the closure captures things, pass them as parameters or
collect them into your own type.</li>
</ul>
<h1 id="references">References<a class="zola-anchor" href="#references" aria-label="Anchor link for: references">§</a>
</h1>
<ul>
<li><a href="https://doc.rust-lang.org/reference/type-coercions.html#coercion-types">Reference - Type Coercions</a></li>
<li><a href="https://github.com/rust-lang/rust/issues/100002">Issue 100002</a></li>
<li><a href="https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723">Issue 41078</a></li>
<li><a href="https://doc.rust-lang.org/stable/error_codes/E0521.html#error-code-e0521">Error E0521</a></li>
<li><a href="https://users.rust-lang.org/t/why-does-the-type-annotation-incur-the-reborrow/88479/10">Why does the type annotation incur the reborrow?</a></li>
<li><a href="https://users.rust-lang.org/t/why-closure-cannot-return-a-reference-to-data-moved-into-closure/72655">Why closure cannot return a reference to data moved into closure</a></li>
</ul>


        
    

        
        
    </article></div>
    <div class="pagination">
        <div class="pagination__buttons">
            </div>
    </div>
<footer class="footer">
                    <div class="footer__inner"><div class="copyright">
            <span>© 2024 Tinusgraglin <span/>
            <span>:: Powered by <a href="https://www.getzola.org/">Zola</a>(<a href="https://www.rust-lang.org/">Rust</a>) and <a href="https://bun.sh">Bun</a>(<a href="https://ziglang.org">Zig</a>)</span>
        </div>
    <script type="text/javascript" src="/blog/assets/js/main.js"></script>
</div>
                    

                </footer></div>
    </body>
</html>
